package com.mk.cloud.common.controller;

import act.apidoc.Description;
import act.controller.Controller;
import act.inject.DefaultValue;
import act.validation.NotBlank;
import com.alibaba.fastjson.JSON;
import com.mk.cloud.Application;
import com.mk.cloud.common.domain.CpCusResource;
import com.mk.cloud.common.domain.CpResource;
import com.mk.cloud.common.domain.CpUser;
import com.mk.cloud.common.enums.ErrorCode;
import com.mk.cloud.common.enums.GlobalValues;
import com.mk.cloud.common.exception.UserException;
import com.mk.cloud.common.interceptor.ITransacte;
import com.mk.cloud.common.interceptor.cookie.CookieService;
import com.mk.cloud.common.interceptor.cookie.ICLogin;
import org.osgl.util.S;import com.mk.cloud.common.util.S2;
import org.osgl.mvc.annotation.*;
import org.osgl.mvc.result.Result;
import org.osgl.util.C;

import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@SuppressWarnings("unused")
@Controller("cpResource")
public class CpResourceController extends CookieService {
    @Inject
    private CpResource.Mapper cpResourceMapper;

    //获取用户权限菜单等
    private CpCusResource userCusResource(CpUser user){
        //region 读取菜单
        List<CpResource> resourceList;
        if(S.eq(user.getUserid(),"1")){
            //超级用户
            CpResource resource = new CpResource();
            resource.setRebelongtype("0");
            resourceList = cpResourceMapper.template(resource);
        }else {
            if(S.eq(user.getUsertype(),GlobalValues.USERTYPE_0.value())){
                resourceList = cpResourceMapper.backGetResByUserid(user.getUserid());
            }else {
                resourceList = cpResourceMapper.frontGetResByUserid(user.getUserid());
            }
        }
        //无权访问
        UserException.throwIf(resourceList.isEmpty(),ErrorCode.E201004);

        //region解析菜单
        CpCusResource urls = new CpCusResource();
        Map<String, String> url_map = new HashMap<>();
        List<CpResource> res = new ArrayList<>();
        List<String> ids = new ArrayList<>();
        resourceList.forEach(a -> {
            if (a.getResourcepid() != null) {
                List<CpResource> tempList = resourceList
                        .stream()
                        .filter(d -> d.getId().equals(a.getResourcepid()))
                        .collect(Collectors.toList());
                if (!tempList.isEmpty()) {
                    CpResource temp = tempList.get(0);
                    if (temp.getMenus() == null) temp.setMenus(new ArrayList<>());
                    temp.getMenus().add(a);
                    ids.add(a.getId());
                }
            }
        });
        resourceList.forEach(a -> {
            if (ids.stream().noneMatch(b -> b.equals(a.getId()))) {
                a.setLevel(1);
                if (S.isNotBlank(a.getResourceurl())) {
                    if (S.isBlank(urls.getFirst())) urls.setFirst(a.getResourceurl());
                    url_map.put(a.getResourceurl(), a.getId().toString());
                }
                if (a.getMenus() != null) {
                    a.getMenus().forEach(b -> {
                        if (S.isNotBlank(b.getResourceurl()))
                            url_map.put(b.getResourceurl(), a.getId() + "-" + b.getId());
                        if (S.isNotBlank(b.getResourceurl())) {
                            if (S.isBlank(urls.getFirst())) urls.setFirst(b.getResourceurl());
                            if (S.isBlank(a.getResourceurl())) a.setResourceurl(b.getResourceurl());
                        }
                        if (b.getMenus() != null && !b.getMenus().isEmpty()) {
                            a.setLevel(2);
                            b.getMenus().forEach(c -> {
                                if (S.isNotBlank(c.getResourceurl())) {
                                    if (S.isBlank(urls.getFirst())) urls.setFirst(c.getResourceurl());
                                    if (S.isBlank(a.getResourceurl())) a.setResourceurl(c.getResourceurl());
                                    if (S.isBlank(b.getResourceurl())) b.setResourceurl(c.getResourceurl());
                                    url_map.put(c.getResourceurl(), a.getId() + "-" + b.getId() + "-" + c.getId());
                                }
                            });
                        }
                    });
                }
                res.add(a);
            }
        });
        //endregion
        urls.setRes(res);
        urls.setUrl(url_map);
        System.out.println(JSON.toJSONString(urls));
//        context.session().cache("urls", urls, Application.CACHE_TIME);
        return urls;
    }


    @Description("获取当前登录人资源列表")
    @With(ICLogin.class)
    @GetAction("getRes.json")
    public CpCusResource getMyRes(){
        return userCusResource(me);
    }


    @Description("获取按钮权限们")
    @With(ICLogin.class)
    @GetAction("getPermissions.json")
    public List<String> getPermissions() {
        List<String> a = cpResourceMapper.getPermissions(me.getUserid());
        return a;
    }

    /**
     * 递归的将所有子类都赋予父类的属性
     * @param dto
     * @param list
     */
    private void findSon(CpResource dto,List<CpResource> list){
        List<CpResource> sublist = list.stream().filter(
                d->S.eq(d.getResourcepid(),(dto.getResourceid()))
        ).collect(Collectors.toList());
        if(!sublist.isEmpty()){
            sublist.forEach(subdto->{
                findSon(subdto,list);
            });
            dto.setMenus(sublist);
        }
    }

    /**
     * 资源请求
     *
     * @return
     */
    @GetAction("list.json")
    @With(ICLogin.class)
    @Description("通用-资源列表请求-资源树(已实现)")
    public List<CpResource> listRes(
            @Description("资源所属平台，0-平台，1-客户")
            @NotBlank @DefaultValue("0") String rebelongtype,
            @Description("角色id")
            String roleid
    ) {
        CpResource cpResource = new CpResource();
        cpResource.setRebelongtype(rebelongtype);
        List<CpResource> list = cpResourceMapper.template(cpResource);
        List<CpResource> result = new ArrayList<>();
        list.forEach( dto ->{
            findSon(dto,list);
            if(S.isBlank(dto.getResourcepid())){
                result.add(dto);
            }
        });
        return result;
    }

    @GetAction("ssoroleResourceTree.json")
    @With(ICLogin.class)
    @Description("通用-角色-角色资源树，返回该角色拥有的资源树列表(已实现)")
    public List<CpResource> ssoroleResource(
            @Description("资源所属平台，0-平台，1-客户")
            @NotBlank @DefaultValue("0") String rebelongtype,
            @Description("角色主键")
            @NotBlank String roleid
    ){
        List<CpResource> result = new ArrayList();
        List<CpResource> list = null;
        if(S.neq(me.getUsertype(),GlobalValues.USERTYPE_0.value())){
            list = cpResourceMapper.frontGetResByRoleidCustomer(roleid);
        }else{
            if(S.eq(rebelongtype,"0")){
                list = cpResourceMapper.backGetResByRoleid(roleid);
            }else if(S.eq(rebelongtype,"1")){
                list = cpResourceMapper.frontGetResByRoleid(roleid);
            }
        }
        if(list!=null&&list.size()>0){
            List<CpResource> finalList = list;
            list.forEach(dto ->{
                findSon(dto, finalList);
                if(dto.getMenus()==null||dto.getMenus().size()==0){
                    result.add(dto);
                }
            });
        }
        return result;
    }

    @GetAction("ssoroleResourceTreeTemp.json")
    @With(ICLogin.class)
    @Description("通用-角色-角色资源树，返回该角色拥有的资源树列表(已实现)")
    public List<CpResource> ssoroleResourceTemp(
            @Description("资源所属平台，0-平台，1-客户")
            @NotBlank @DefaultValue("0") String rebelongtype,
            @Description("角色主键")
            @NotBlank String roleid
    ){
        return cpResourceMapper.frontGetResByRoleid(roleid);
    }


    @GetAction("{resourceid}/resource.json")
    @With(ICLogin.class)
    @Description("通用-获取资源对象(已实现)")
    public CpResource getRes(
            @Description("资源id")
            @NotNull String resourceid) {
        return cpResourceMapper.getResourceByKey(resourceid);
    }


    @PostAction("add.json")
    @With({ICLogin.class, ITransacte.class})
    @Description("通用-新增资源，返回新增资源的主键(已实现)")
    public String addRes(
            @Description("要增加的资源对象")
            @NotNull(message = "必须传递资源数据") @Valid CpResource cpResource
    ){
        UserException.throwIf(S.isBlank(cpResource.getResourcecode())||S.isBlank(cpResource.getRebelongtype()),ErrorCode.E200000);
        String sameCodeName = cpResourceMapper.comCheckResourceCode(cpResource.getResourcecode(),null);
        UserException.throwIf(S.isNotBlank(sameCodeName), S.fmt("编码%s已经被菜单:%s使用!", cpResource.getResourcecode(), sameCodeName));
        cpResource.setResourceid(S2.UUID());
        cpResourceMapper.insert(cpResource);
        return cpResource.getResourceid();
    }

    @PutAction("update.json")
    @With({ICLogin.class, ITransacte.class})
    @Description("通用-修改资源，返回更新资源的主键(已实现)")
    public String updateRes(
            @Description("要更新的资源对象")
            @NotNull(message = "必须传递资源数据") @Valid CpResource cpResource
    ){
        String sameCodeName = cpResourceMapper.comCheckResourceCode(cpResource.getResourcecode(),cpResource.getResourceid());
        UserException.throwIf(S.isNotBlank(sameCodeName), S.fmt("编码%s已经被菜单:%s使用!", cpResource.getResourcecode(), sameCodeName));
        cpResourceMapper.updateTemplateById(cpResource);
        return cpResource.getResourceid();
    }

    /**
     * 删除资源
     *
     * @param resourceid
     * @return
     */
    @DeleteAction("{resourceid}/del.json")
    @With({ICLogin.class, ITransacte.class})
    @Description("通用-删除资源，返回删除资源的条数(已实现)")
    public int delRes(
            @NotNull(message = "必须指定要删除的记录") String resourceid
    ) {
        int res = cpResourceMapper.comDeleteResourceById(resourceid);
        return res;
    }


    /**
     * 保存资源结构
     *
     * @param json
     * @return
     */
    @PutAction("save.json")
    @With({ICLogin.class, ITransacte.class})
    @Description("通用-保存资源排序和结构(已实现)")
    public void saveStructureRes(
            @NotNull(message = "没有传递数据!") String json
    ) {
        List<CpResource> res = JSON.parseArray(json, CpResource.class);
        cpResourceMapper.comSaveResourceStructure(res);
    }



    /************************* 本系统不保留跳转页面相关的接口  ****************************/

    /**
     * 展示资源表单
     *
     * @param resourceid
     * @param resourcepid
     * @return
     */
//    @GetAction("form.html")
    @With(ICLogin.class)
    public Result formRes(String resourceid,
                          String resourcepid) {
        boolean isAdd = resourceid == null;
        CpResource cpResource;
        if (isAdd) {
            cpResource = new CpResource();
            cpResource.setResourcestate(GlobalValues.COMMON_1.value());
            cpResource.setResourcepid(resourcepid);
        } else {
            cpResource = cpResourceMapper.unique(resourceid);
        }
        return render(cpResource, isAdd);
    }

    /**
     * 保存资源
     *
     * @param cpResource
     * @param isAdd
     * @return
     */
//    @PostAction("save.html")
    @With({ICLogin.class, ITransacte.class})
    @ResponseStatus(200)
    public Result saveRes(
        @NotNull(message = "必须传递资源数据") @Valid CpResource cpResource,
        @NotNull(message = "未知存储类型") Boolean isAdd) {
        if (S.isBlank(cpResource.getResourcestate())) {
            cpResource.setResourcestate(GlobalValues.COMMON_0.value());
        }
        if (cpResource.getOrderno() == null || cpResource.getOrderno() == 0) {
            cpResource.setOrderno(cpResourceMapper.getSQLManager().intValue("application.select_resource_max_order", int.class));
        }
        String sameCodeName = cpResourceMapper
            .getSQLManager()
            .selectSingle(
                "application.check_resource_code",
                C.Map("resourcecode", cpResource.getResourcecode(), "resourceid", cpResource.getResourceid()),
                String.class
            );
        UserException.throwIf(S.isNotBlank(sameCodeName), S.fmt("编码%s已经被菜单:%s使用!", cpResource.getResourcecode(), sameCodeName));
        if (isAdd) cpResourceMapper.insert(cpResource);
        else cpResourceMapper.updateTemplateById(cpResource);
        return render("/util/success.html");
    }




}
